﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Modbus.IO;
using Modbus.Device;
using System.IO.Ports;
using Microsoft.Win32;

namespace demo1
{
    public partial class Form1 : Form
    {
        /// <summary>
        ///  准备参数
        /// </summary>
        private string[] connectType = { "SerialPort" };
        private int[] serialBaud = { 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000, 230400, 25600 };
        private int[] serialDataBit = { 5, 6, 7, 8 };
        private double[] serialStopBitCbb = { 1, 1.5, 2 };
        private StopBits[] serialStopBit = { StopBits.One, StopBits.OnePointFive, StopBits.Two };
        private string[] serialParityCbb = { "None Parity", "Odd Parity", "Even Parity" };
        private Parity[] serialParity = { Parity.None, Parity.Odd, Parity.Even };

        private string[] op_string = { "读线圈(01H)", "读离散输入(02H)", "读保持寄存器(03H)", "读输入寄存器(04H)" };
        private byte[] op_code = { 0x01, 0x02, 0x03, 0x04 };

        private SerialPort m_serialPort = null;
        private ModbusSerialMaster m_serialMaster;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            m_serialPort = new SerialPort();
            // ui 连接类型
            connectType_cbb.DataSource = connectType;

            // UI 串口号加载
            RegistryKey keyCom = Registry.LocalMachine.OpenSubKey(@"Hardware\DeviceMap\SerialComm");
            if (keyCom != null)
            {
                string[] subKeys = keyCom.GetValueNames();         //获取所有存在的串口号并以数组暂存

                serialPort_cbb.Items.Clear();
                foreach (string name in subKeys)					//循环将端口信息添加到cobport中
                {
                    string sValue = (string)keyCom.GetValue(name);
                    serialPort_cbb.Items.Add(sValue);
                }
                serialPort_cbb.SelectedIndex = 0;
            }

            // 波特率
            //serialBaud_cbb.DataSource = serialBaud;
            //serialBaud_cbb.SelectedIndex = 11;

            //serialDatabit_cbb.DataSource = serialDataBit;
            //serialDatabit_cbb.SelectedIndex = 3;

            //serialParity_cbb.DataSource = serialParityCbb;
            //serialParity_cbb.SelectedIndex = 0;

            //serialStopbit_cbb.DataSource = serialStopBitCbb;
            //serialStopbit_cbb.SelectedIndex = 0;


            foreach (int baud in serialBaud)
            {
                serialBaud_cbb.Items.Add(baud + " Baud");
            }
            serialBaud_cbb.SelectedIndex = 11;

            foreach (int dataBit in serialDataBit)
            {
                serialDatabit_cbb.Items.Add(dataBit + " Data Bits");
            }
            serialDatabit_cbb.SelectedIndex = 3;

            foreach (string parity in serialParityCbb)
            {
                serialParity_cbb.Items.Add(parity);
            }
            serialParity_cbb.SelectedIndex = 0;

            foreach (double stopBit in serialStopBitCbb)
            {
                serialStopbit_cbb.Items.Add(stopBit + " Stop Bit");
            }
            serialStopbit_cbb.SelectedIndex = 0;

            option_cbb.DataSource = op_string;

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (m_serialPort.IsOpen)
            {
                m_serialPort.Close();
            }
        }

        private void connect_btn_Click(object sender, EventArgs e)
        {
            // switch 
            if (connectType_cbb.Text == connectType[0])
            {
                if (!m_serialPort.IsOpen)
                {
                    try
                    {
                        m_serialPort.PortName = serialPort_cbb.Text;
                        m_serialPort.BaudRate = serialBaud[serialBaud_cbb.SelectedIndex];
                        m_serialPort.DataBits = serialDataBit[serialDatabit_cbb.SelectedIndex];
                        m_serialPort.StopBits = serialStopBit[serialStopbit_cbb.SelectedIndex];
                        m_serialPort.Parity = serialParity[serialParity_cbb.SelectedIndex];

                        m_serialPort.Open();
                        if (RTU_rbtn.Checked)
                        {
                            m_serialMaster = ModbusSerialMaster.CreateRtu(m_serialPort);
                        }
                        if (ASCII_rbtn.Checked)
                        {
                            m_serialMaster = ModbusSerialMaster.CreateAscii(m_serialPort);
                        }
                        connect_btn.Text = "断开";
                    }
                    catch (Exception)
                    {

                        throw;
                    }

                }
                else
                {
                    try
                    {
                        if (m_serialPort.IsOpen)
                        {
                            m_serialPort.Close();
                        }
                        connect_btn.Text = "连接";
                    }
                    catch (Exception)
                    {

                        throw;
                    }
                }

            }
        }

        private void read_btn_Click(object sender, EventArgs e)
        {
            byte station = Convert.ToByte(station_txb.Text);
            ushort address = Convert.ToUInt16(startAddress_txb.Text);
            ushort num = Convert.ToUInt16(num_txb.Text);

            switch (option_cbb.SelectedIndex)
            {
                case 0:
                    bool[] result = m_serialMaster.ReadCoils(station, address, num);
                    break;
                case 1:
                    bool[] result1 = m_serialMaster.ReadInputs(station, address, num);
                    break;
                case 2:
                    ushort[] result2 = m_serialMaster.ReadHoldingRegisters(station, address, num);
                    break;
                case 3:
                    ushort[] result3 = m_serialMaster.ReadInputRegisters(station, address, num);
                    break;

                default:
                    break;
            }
        }
    }
}
